# github有很多中文词向量预训练模型  
# ChineseWordVectors
# 里面有百度百科上训练的版本
# 这文件里有大量训练好的中文词汇  
# 每个词向量维度是300

# chinese_vec.py是帮助大家读取这模型的辅助代码  
import chinese_vec

import shopping_data 

Xtrain,Ytrain,Xtest,Ytest = shopping_data.load_data()

print(Xtrain.shape)
print(Ytrain.shape)
print(Xtest.shape)
print(Ytest.shape)

vocalen,word_index = shopping_data.createWordIndex(Xtrain,Xtest)
print(vocalen,word_index)

#我 是 你爹 = [100,150,199]
Xtrain_index = shopping_data.word2Index(Xtrain,word_index)
Xtest_index = shopping_data.word2Index(Xtest,word_index)

from keras.preprocessing import sequence

maxlen = 25

Xtrain_index = sequence.pad_sequences(Xtrain_index,maxlen=maxlen)
Xtest_index = sequence.pad_sequences(Xtest_index,maxlen=maxlen)

# 自行构造词嵌入矩阵
word_vecs = chinese_vec.load_word_vecs()
# dict key是词汇 value是对应词向量

import numpy as np
embedding_matrix = np.zeros((vocalen,300))
# 创建0矩阵  形状是上节课情感分类任务重全部语料词汇的数量
# 即词汇表的数量乘以每个词向量的维度300  
# 也就是待会用来替换的嵌入层之前自己构建的嵌入矩阵的形状

# 从刚才加载出来的预训练词向量集合中  
# 找到这些词的词向量 填充到embedding_matrix  
# word是词典索引中一个词的文本  i是索引值
for word , i in word_index.items():
    embedding_vector = word_vecs.get(word)
    if embedding_vector is not None:
        embedding_matrix[i]=embedding_vector
# 这样下来  我们自己创建的embedding_matrix
# 就是一个别人训练好的词向量构成的词嵌入矩阵了  
# 这样就可以把嵌入式层的嵌入矩阵给替换掉  


from keras.models import Sequential
from keras.layers import Dense, Embedding, LSTM 

#创建模型
model = Sequential()

# 嵌入式层  不训练 并且加入替换好的词嵌入矩阵
model.add(Embedding(trainable=False,
                    weights=[embedding_matrix],
                    input_dim=vocalen,
                    ouput_dim=300,
                    input_length=maxlen
                    )
        )

# 两层lstm
model.add(LSTM(128,return_sequences=True))
model.add(LSTM(128))
# 多层RNN 前面的层需要再序列的每一步都输出结果  
# 作为下一步的输入  
# 所以第一层lstm需配置return_sequences  
# 默认是false只在最后输出结果  


model.add(Dense(units=1,activation='sigmoid'))
# 损失函数 二分类交叉熵代函数 
# 梯度优化器 动量的自适应优化器 比sgd更快更好
model.compile(loss='binary_crossentropy',
              optimizer='adam',
              metrics=['accuracy']
              )

model.fit(Xtrain_index,Ytrain,batch_size=512,epochs=200)

score, acc = model.evaluate(Xtest_index,Ytest)
print(score, acc)

# 结论：
# 准确率又上升了一些  
# 趋势很明显
# 用lstm的准确率比全连接神经网络高   

# 不适用预训练词向量 也不自己训练 效果最差
# 自己训练词向量 有所上升  
#     但词向量特征太多 最后出来准确率 在lstm和fc上差距无几
# 使用第三方预训练词向量 效果不错  
